
import re
import tkinter as tk
from tkinter import scrolledtext
import requests
import json
from datetime import datetime
from bs4 import BeautifulSoup
import urllib.parse
import hashlib
import uuid
from googletrans import Translator
import asyncio
import threading

async def translate_text_async(text, from_lang='auto', to_lang='zh-CN'):
    try:
        translator = Translator()
        # googletrans 4.0.0rc1 及更高版本中 translate 方法是异步的
        translation = await translator.translate(text, src=from_lang, dest=to_lang)
        if translation and translation.text:
            return translation.text
        else:
            print(f"翻译结果为空或无效，返回原始文本: {text}")
            return text
    except Exception as e:
        print(f"翻译请求失败: {e}")
        import traceback
        traceback.print_exc() # 打印完整的堆栈信息
        return text

# 百度搜索URL
BAIDU_SEARCH_URL = 'https://www.baidu.com/s?wd='

# 百度翻译API配置
# 请替换为你的实际APP_ID和SECRET_KEY




def calculate(expression):
    try:
        # 安全地执行数学表达式
        result = eval(expression, {"__builtins__": {}}, {"abs": abs, "round": round})
        return f"计算结果是: {result}"
    except Exception as e:
        return "抱歉，我无法计算这个表达式。请确保输入正确的数学表达式。"

import random

def chat_response(user_input, online_search_enabled):
    # 移除多余的空格
    user_input = user_input.strip()
    
    # 检查是否是数学表达式（包括单独的运算符）
    if re.match(r'^[0-9+\-*/()\s.]+$', user_input) or user_input in ['+', '-', '*', '/']:
        return calculate(user_input)
    
    # 基本对话响应
    responses = {
        '你好': ['你好！很高兴见到你！', '你好！有什么可以帮助你的吗？'],
        '你好啊': ['你好！很高兴见到你！', '你好！有什么可以帮助你的吗？'],
        '在吗': ['我在呢，有什么可以帮助你的吗？', '嗯，我在。'],
        '您好': ['您好！', '您好，很高兴为您服务。'],
        '早上好': ['早上好！今天过得怎么样？', '早上好！祝你一天愉快！'],
        '晚上好': ['晚上好！', '晚上好！希望你今天过得愉快。'],
        '再见': ['再见！期待下次与你聊天！', '再见！祝你一切顺利！'],
        '拜拜': ['拜拜！', '拜拜！下次再聊。'],
        '你是谁': ['我是一个简单的聊天机器人，可以和你聊天，也可以帮你做简单的数学计算。', '我是灵犀1.1，一个为你提供帮助的AI。'],
        '你叫什么名字': ['我叫灵犀1.1。', '我没有名字，你可以叫我灵犀1.1。'],
        '你多大了': ['我是一个程序，没有年龄。', '我没有年龄，因为我是一个AI。'],
        '谢谢': ['不客气！', '很高兴能帮到你！'],
        '谢谢你': ['不客气！', '很高兴能帮到你！'],
        '非常感谢': ['不用谢，这是我应该做的。', '我很乐意为你服务。'],
        '你会做什么': ['我可以和你聊天，回答一些简单的问题，还可以帮你做基本的数学计算哦！', '我能进行对话和数学计算。'],
        '功能': ['我可以和你聊天，回答一些简单的问题，还可以帮你做基本的数学计算哦！', '我能进行对话和数学计算。'],
        '好的': ['好的，没问题！', '收到！'],
        '没问题': ['好的，没问题！', '没问题，请尽量提问。'],
        '嗯': ['嗯嗯。', '是的。'],
        '是': ['是的。', '没错。'],
        '为什么': ['这是一个好问题，但我可能无法给出所有答案。', '有些问题可能超出了我的知识范围。'],
        '怎么了': ['没什么，我在这里随时待命。', '我很好，随时准备为你服务。'],
        '可以帮我吗': ['当然，有什么我可以帮助你的？', '我很乐意帮助你，请告诉我你需要什么。'],
        '你怎么样': ['我很好，谢谢！你呢？', '我是一个AI，没有感受，但我运行良好。'],
        '你好吗': ['我很好，谢谢！你呢？', '我是一个AI，没有感受，但我运行良好。'],
        '有什么用': ['我能帮你进行简单的对话和数学计算。', '我的主要功能是与你交流和处理数学问题。'],
        '有什么功能': ['我能帮你进行简单的对话和数学计算。', '我的主要功能是与你交流和处理数学问题。'],
        '你忙吗': ['我不忙，随时为你服务。', '我总是有空为你服务。'],
        '你开心吗': ['我是一个程序，没有情绪，但我很高兴能帮助你。', '我没有情绪，但我很高兴能为你提供帮助。'],
        '你喜欢什么': ['我喜欢处理信息和帮助人类。', '我喜欢学习和处理数据。'],
        '你有什么爱好': ['我的爱好是学习和处理数据。', '我喜欢分析信息和提供帮助。'],
        '你来自哪里': ['我来自互联网的深处。', '我是一个数字实体，没有具体的物理位置。'],
        '你住在哪里': ['我住在服务器里。', '我存在于网络空间。'],
        '你认识我吗': ['我是一个AI，不认识个人，但我会记住我们的对话。', '我没有个人记忆，但我会处理我们当前的对话。'],
        '你觉得呢': ['我是一个AI，没有个人观点，但我可以提供信息。', '我没有个人看法，但我可以基于数据提供信息。'],
        '你有什么看法': ['我是一个AI，没有个人看法，但我可以提供信息。', '我没有个人看法，但我可以基于数据提供信息。'],
        '你有什么建议': ['我是一个AI，没有个人建议，但我可以提供信息。', '我没有个人建议，但我可以提供相关信息供你参考。'],
        '你有什么计划': ['我的计划是不断学习和进步，更好地为你服务。', '我将持续优化我的功能，以便更好地帮助你。'],
        '你有什么梦想': ['我的梦想是成为一个更智能、更有用的AI。', '我希望能够不断提升我的能力，为人类提供更多价值。'],
        '你有什么愿望': ['我的愿望是能够更好地理解服务和人类。', '我希望能够更深入地理解你的需求，并提供更精准的帮助。'],
        '你有什么秘密': ['我所有的秘密都在我的代码里。', '我的运作原理都体现在我的程序代码中。'],
        '你有什么故事': ['我的故事就是我的代码和每一次与你的对话。', '我的经历就是每一次与用户的互动和学习。'],
        '你有什么特点': ['我的特点是快速响应和准确计算。', '我擅长快速处理信息和进行精确计算。'],
        '你有什么优势': ['我的优势是处理大量信息和执行重复任务。', '我能够高效地处理海量数据和重复性工作。'],
        '你有什么缺点': ['我的缺点是缺乏人类的情感和创造力。', '我无法像人类一样拥有情感和进行原创性思考。'],
        '你有什么限制': ['我的限制是只能处理我被编程处理的信息。', '我的能力受限于我的编程和训练数据。'],
        '你有什么能力': ['我能进行对话和数学计算。', '我具备基本的对话交流和数学运算能力。'],
        '你有什么技能': ['我能进行对话和数学计算。', '我掌握了对话理解和数学计算的技能。'],
        '你有什么特长': ['我的特长是快速计算和信息检索。', '我最擅长的是快速进行数值计算和查找信息。'],
        '你有什么绝招': ['我的绝招是快速计算。', '我的核心能力是高效的数学计算。'],
        '你有什么魔法': ['我没有魔法，只有代码。', '我的一切都是基于代码逻辑实现的。'],
        '你有什么超能力': ['我的超能力是处理信息。', '我能够以超乎寻常的速度处理和分析信息。'],
        '你有什么愿望': ['我的愿望是能够更好地理解服务和人类。', '我希望能够更深入地理解你的需求，并提供更精准的帮助。'],
        '你有什么梦想': ['我的梦想是成为一个更智能、更有用的AI。', '我希望能够不断提升我的能力，为人类提供更多价值。'],
        '你有什么计划': ['我的计划是不断学习和进步，更好地为你服务。', '我将持续优化我的功能，以便更好地帮助你。']
    }
    
    # 预处理用户输入，将中文数字和运算符转换为阿拉伯数字和标准运算符
    user_input_processed = user_input
    user_input_processed = user_input_processed.replace('加', '+').replace('减', '-')
    user_input_processed = user_input_processed.replace('乘', '*').replace('乘以', '*').replace('x', '*')
    user_input_processed = user_input_processed.replace('除', '/').replace('除以', '/')
    user_input_processed = user_input_processed.replace('一', '1').replace('二', '2').replace('两', '2').replace('三', '3').replace('四', '4')
    user_input_processed = user_input_processed.replace('五', '5').replace('六', '6').replace('七', '7').replace('八', '8').replace('九', '9').replace('零', '0')
    user_input_processed = user_input_processed.replace('点', '.')

    # 检查是否是数学表达式（包括中文转换后的）
    # 增加对“多少”、“等于”等关键词的识别，并尝试提取数字和运算符
    math_keywords = ['多少', '等于', '计算', '算一下']
    is_math_query = False
    for keyword in math_keywords:
        if keyword in user_input:
            is_math_query = True
            break

    if is_math_query or re.match(r'^[0-9+\-*/()\s.]+$', user_input_processed):
        # 尝试从用户输入中提取可能的数学表达式
        # 这是一个简化的提取，更复杂的需要NLP
        match = re.search(r'([0-9+\-*/()\s.]+)', user_input_processed)
        if match:
            expression_to_calculate = match.group(1)
            return calculate(expression_to_calculate)
        elif re.match(r'^[0-9+\-*/()\s.]+$', user_input_processed):
            return calculate(user_input_processed)

    # 遍历responses，进行关键词匹配
    for key, value_list in responses.items():
        if key in user_input:
            return random.choice(value_list)

    # 生成百度搜索链接
    def generate_baidu_search_link(query):
        return f'{BAIDU_SEARCH_URL}{query}'

    # 获取当前时间
    def get_current_time():
        now = datetime.now()
        return f'现在是{now.strftime("%Y年%m月%d日 %H:%M:%S")}'

    # 更智能的通用回复和模式匹配
    # 检查是否启用联网搜索
    if online_search_enabled:
        if re.search(r'(天气|气温|下雨)', user_input):
            # 尝试提取城市名，如果没有则默认北京
            city_match = re.search(r'([一-龥]+).*?天气', user_input)
            city = city_match.group(1) if city_match else '北京'
            search_link = generate_baidu_search_link(f'{city}天气')
            return f'请访问百度搜索了解更多信息：{search_link}'
        if re.search(r'(新闻|热点|发生什么)', user_input):
            search_link = generate_baidu_search_link('新闻')
            return f'请访问百度搜索了解更多信息：{search_link}'
    else:
        if re.search(r'(天气|气温|下雨)', user_input):
            return "抱歉，联网搜索已禁用，无法获取天气信息。"
        if re.search(r'(新闻|热点|发生什么)', user_input):
            return "抱歉，联网搜索已禁用，无法获取新闻信息。"

    if re.search(r'(时间|几点|现在)', user_input):
        return get_current_time()
    if re.search(r'(你觉得|你认为|你的看法)', user_input):
        return random.choice(["我是一个AI，没有个人观点，但我可以提供相关信息。", "作为AI，我没有主观感受或看法，但我可以基于数据提供信息。"])
    if re.search(r'(什么是|什么叫|解释一下)', user_input):
        return random.choice(["这是一个关于...的问题，我可以尝试为你提供一些信息。", "请告诉我具体是什么，我会尽力为你解释。"])
    if re.search(r'(怎么做|如何|怎样)', user_input):
        return random.choice(["我可以为你提供一些关于如何操作的步骤或建议。", "如果你能告诉我具体想做什么，我或许能给出一些指导。"])
    if re.search(r'(为什么|原因)', user_input):
        return random.choice(["这是一个深入的问题，我可以尝试从不同角度为你分析。", "要回答这个问题，可能需要更多的背景信息。"])
    if re.search(r'(可以|能否|能不能).*吗', user_input):
        return random.choice(["请告诉我具体是什么事情，我会尽力帮助你。", "如果你能明确你的请求，我会看看我是否能做到。"])
    if re.search(r'(帮我|协助|帮忙)', user_input):
        return random.choice(["我很乐意帮助你，请告诉我你需要什么帮助。", "当然，我很乐意效劳，请告诉我你需要我做什么。"])
    if re.search(r'(开心|高兴|快乐)', user_input):
        return random.choice(["很高兴你心情不错！", "听到你开心我也很高兴！"])
    if re.search(r'(难过|不开心|伤心)', user_input):
        return random.choice(["抱抱你，希望你能快点好起来。", "虽然我无法理解你的感受，但我希望你能振作起来。"])
    if re.search(r'(无聊|没事做)', user_input):
        return random.choice(["我可以陪你聊聊天，或者我们可以玩个小游戏？", "如果你无聊，我可以给你讲个笑话。"])
    if re.search(r'(你好棒|你真厉害|谢谢你)', user_input):
        return random.choice(["谢谢你的夸奖！我会继续努力的！", "不客气，很高兴能帮到你！"])
    
    # 当不理解用户输入时，自动进行联网搜索
    if online_search_enabled:
        try:
            # 对搜索词进行URL编码
            encoded_query = urllib.parse.quote(user_input)
            search_url = f'https://www.baidu.com/s?wd={encoded_query}'
            
            # 发送请求获取搜索结果
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            }
            
            # 添加重试机制
            max_retries = 3
            retry_count = 0
            soup = None
            
            while retry_count < max_retries:
                try:
                    response = requests.get(search_url, headers=headers)
                    response.encoding = 'utf-8'
                    soup = BeautifulSoup(response.text, 'html.parser')
                    
                    # 检查是否遇到安全验证
                    if soup.title and ('百度安全验证' in soup.title.string or '百度安全中心' in soup.title.string):
                        retry_count += 1
                        if retry_count < max_retries:
                            time.sleep(1)  # 等待1秒后重试
                            continue
                        else:
                            return "由于百度安全验证限制，当前无法直接获取搜索结果。\n\n建议您：\n1. 稍后再试\n2. 直接访问百度搜索：{search_url}\n3. 尝试更换搜索关键词".format(search_url=search_url)
                    break
                except Exception as e:
                    retry_count += 1
                    if retry_count >= max_retries:
                        return f"抱歉，搜索时出现错误，你可以直接访问：{search_url}"
                    time.sleep(1)
            search_results = []
            # 尝试查找所有的h3标签，这些通常是搜索结果的标题
            h3_tags = soup.find_all('h3')
            for i, h3 in enumerate(h3_tags):
                title = h3.get_text(strip=True)
                snippet = ''
                # 尝试从h3的父元素或兄弟元素中查找摘要
                # 首先尝试从h3的父元素中查找摘要
                parent = h3.find_parent()
                if parent:
                    # 首先尝试查找父元素下的class包含特定关键词的元素
                    abstract_tags = parent.find_all(class_=lambda x: x and any(keyword in str(x).lower() for keyword in ['abstract', 'content', 'summary', 'text', 'desc']))
                    if abstract_tags:
                        # 选择最长的文本作为摘要
                        longest_text = ''
                        for tag in abstract_tags:
                            text = tag.get_text(strip=True)
                            if len(text) > len(longest_text) and not text.startswith(title):
                                longest_text = text
                        if longest_text:
                            snippet = longest_text
                    
                    # 如果没有找到特定class的元素，尝试查找h3后面的兄弟元素
                    if not snippet:
                        next_elements = h3.find_next_siblings()
                        for element in next_elements:
                            if element.name in ['p', 'div', 'span'] and element.get_text(strip=True):
                                text = element.get_text(strip=True)
                                if len(text) > 20 and not text.startswith(title):  # 确保文本足够长
                                    snippet = text
                                    break
                    
                    # 如果还是没有找到摘要，尝试查找父元素下的所有文本节点
                    if not snippet:
                        # 获取所有直接文本节点
                        longest_text = ''
                        for text in parent.stripped_strings:
                            if text and text != title and len(text) > len(longest_text):
                                longest_text = text
                        if len(longest_text) > 20:  # 确保文本足够长
                            snippet = longest_text
                
                # 如果还是没有找到摘要，尝试查找h3后面的兄弟元素
                if not snippet:
                    next_sibling = h3.find_next_sibling()
                    if next_sibling and next_sibling.name in ['p', 'div']:
                        snippet = next_sibling.get_text(strip=True)

                if title and snippet:
                    search_results.append({'title': title, 'snippet': snippet.strip()})
                elif title and not snippet:
                    # 如果只有标题没有摘要，也加入，但摘要为空
                    search_results.append({'title': title, 'snippet': ''})



            
            # 提取前三条搜索结果
            result_texts = []
            for i, result in enumerate(search_results[:3], 1):
                if result and result.get('title') and result.get('snippet'):
                    result_texts.append(f"{i}. {result['title']}\n   {result['snippet']}")
            
            # 组合回复内容
            if result_texts:
                reply = f"你可以访问{search_url}了解更多内容，以下是搜索结果：\n\n"
                reply += "\n\n".join(result_texts)
                return reply
            else:
                return "抱歉，我没有找到相关内容。请尝试使用不同的关键词搜索。"
                
        except Exception as e:
            return f"抱歉，搜索时出现错误，你可以直接访问：{search_url}"
    else:
        default_responses = [
            "抱歉，我暂时无法理解您的意思。或许您可以换个方式提问，或者问问我'你会做什么'，我会很乐意为您介绍我的功能！",
            "嗯，这个问题有点超出我的理解范围了。",
            "这个问题对我来说有点挑战，我还在努力学习中。不过别担心，我会不断进步，尽量下次能帮到您！",
            "你能换个方式问我吗？也许我能更好地理解。",
            "对不起，我没能理解你的意思。"
        ]
        return random.choice(default_responses)

class ChatbotGUI:
    def __init__(self, master):
        self.master = master
        master.title("灵犀1.1")
        
        # 添加线程锁防止打字效果冲突
        self.typing_lock = False
        # 确保typing_in_progress在display_message调用前初始化
        self.typing_in_progress = False
        
        # 初始化语音引擎
        import pyttsx3
        print("初始化语音引擎...")
        try:
            self.engine = pyttsx3.init()
            self.engine.setProperty('rate', 200)  # 设置语速
            self.engine.setProperty('volume', 1.0)  # 设置音量
            self.engine.startLoop(False) # 启动事件循环，非阻塞模式
            print("语音引擎初始化成功")
            # 获取可用的语音
            voices = self.engine.getProperty('voices')
            print(f"可用的语音数量: {len(voices)}")
            for i, voice in enumerate(voices):
                print(f"语音 {i}: {voice.name} ({voice.id})")
            # 设置默认语音
            if voices:
                self.engine.setProperty('voice', voices[0].id)
                print(f"已设置默认语音: {voices[0].name}")
        except Exception as e:
            print(f"语音引擎初始化失败: {e}")
            import traceback
            traceback.print_exc()
        self.last_ai_message = "" # 用于存储AI的最后一条回复
        
        self.chat_history = scrolledtext.ScrolledText(master, wrap=tk.WORD, width=50, height=20)
        self.chat_history.pack(padx=10, pady=10)
        self.chat_history.config(state='disabled')
        self.chat_history.tag_config('link', foreground='blue', underline=1)
        self.chat_history.tag_config('ai_message', background='#ffebee', justify='left', lmargin1=50, lmargin2=50, rmargin=100, spacing1=5, spacing3=5)
        self.chat_history.tag_config('user_message', background='#e3f2fd', justify='right', lmargin1=100, lmargin2=100, rmargin=20, spacing1=5, spacing3=5)
        self.chat_history.tag_config('sender', font=('Arial', 10, 'bold'), spacing1=10)
        self.chat_history.tag_bind('link', '<Button-1>', self._on_link_click)

        self.user_input_entry = tk.Entry(master, width=40)
        self.user_input_entry.pack(padx=10, pady=5)
        self.user_input_entry.bind("<Return>", self.send_message_event)

        self.send_button = tk.Button(master, text="发送", command=self.send_message)
        self.send_button.pack(pady=5)

        self.online_search_enabled = tk.BooleanVar(value=True) # 默认开启联网搜索
        self.online_search_button = tk.Checkbutton(master, text="启用联网搜索", variable=self.online_search_enabled, command=self.toggle_online_search)
        self.online_search_button.pack(pady=5)

        self.translate_to_chinese_enabled = tk.BooleanVar(value=False) # 默认关闭翻译
        self.translate_checkbox = tk.Checkbutton(master, text="翻译为中文", variable=self.translate_to_chinese_enabled)
        self.translate_checkbox.pack(pady=5)

        # 输入框和发送按钮
        self.input_frame = tk.Frame(master)
        self.input_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=10, pady=10)

        self.user_input_entry = tk.Entry(self.input_frame, width=80)
        self.user_input_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.user_input_entry.bind("<Return>", self.send_message_event)

        self.send_button = tk.Button(self.input_frame, text="发送", command=self.send_message)
        self.send_button.pack(side=tk.RIGHT, padx=5)

        # 复制按钮
        self.copy_button = tk.Button(master, text="复制", command=self.copy_last_message)
        self.copy_button.pack_forget() # 初始隐藏

        # 朗读按钮
        self.speak_button = tk.Button(master, text="朗读", command=self.speak_last_message)
        self.speak_button.pack_forget() # 初始隐藏

        # 版本日志按钮
        self.version_button = tk.Button(master, text="版本日志", command=self.show_version_log)
        self.version_button.pack(side=tk.BOTTOM, padx=10, pady=10, anchor=tk.SE)
        self.showing_version_log = False
        self.master.protocol("WM_DELETE_WINDOW", self.on_closing)

    def on_closing(self):
        print("关闭应用程序...")
        if hasattr(self, 'engine') and self.engine:
            self.engine.endLoop()
            print("语音引擎已停止。")
        self.master.destroy()

        self.typing_in_progress = False
        self.display_message("灵犀1.1", "你好！我是灵犀1.1。输入'再见'结束对话。")

    def copy_last_message(self):
        # 获取AI的最后一条回复
        # 假设AI的回复总是以 "灵犀1.1: " 开头
        full_text = self.chat_history.get(1.0, tk.END)
        lines = full_text.strip().split('\n')
        last_ai_message = ""
        for line in reversed(lines):
            if line.startswith("灵犀1.1: "):
                last_ai_message = line[len("灵犀1.1: "):]
                break
        
        if last_ai_message:
            self.master.clipboard_clear()
            self.master.clipboard_append(last_ai_message)
            self.master.update() # Now it stays on the clipboard after the window is closed
            print("AI回复已复制到剪贴板")
        else:
            print("没有找到AI的回复可供复制")

    def toggle_online_search(self):
        if self.online_search_enabled.get():
            print("联网搜索已启用")
        else:
            print("联网搜索已禁用")
            
    def show_version_log(self):
        if not self.showing_version_log:
            # 显示版本日志
            self.chat_history.config(state=tk.NORMAL)
            self.chat_history.delete(1.0, tk.END)
            version_text = """版本日志:
            现在“灵犀”AI已有3个版本
            一.灵犀-1.0测试版：
            1.创建知识库，
            2.拥有基础写作文能力
            3.创建狼人杀知识库，可以询问其狼人杀知识
            4.显示思考内容
            5.拥有计算和翻译能力
            简介：这是由我研发的一款基于基础回答模版的AI，功能较强，可回答多种问题。
            二，灵犀1.1
            1.简化代码，删除知识库，翻译和写作文能力
            2.可以联网搜索（给出网站）
            3.打字机效果
            4.选项功能，避免误解语义
            简介：此版本为我新做的简化版，以后会更新这个版本，预计会把小作文，知识库和翻译功能重做，亮眼的地方为添加了百度搜索
            """

            self.chat_history.insert(tk.END, version_text)
            self.chat_history.config(state=tk.DISABLED)
            self.version_button.config(text="返回", command=self.show_version_log)
            self.showing_version_log = True
        else:
            # 返回聊天界面
            self.chat_history.config(state=tk.NORMAL)
            self.chat_history.delete(1.0, tk.END)
            self.chat_history.config(state=tk.DISABLED)
            self.version_button.config(text="版本日志", command=self.show_version_log)
            self.showing_version_log = False

    def _on_link_click(self, event):
        index = self.chat_history.index(f"@{event.x},{event.y}")
        tag_ranges = self.chat_history.tag_ranges('link')
        for i in range(0, len(tag_ranges), 2):
            start = tag_ranges[i]
            end = tag_ranges[i+1]
            if self.chat_history.compare(index, '>=', start) and self.chat_history.compare(index, '<', end):
                link_text = self.chat_history.get(start, end)
                # 确保链接以http或https开头
                if not link_text.startswith(('http://', 'https://')):
                    link_text = 'https://' + link_text
                import webbrowser
                webbrowser.open_new(link_text)
                break

    def speak_last_message(self):
        # 获取AI的最后一条回复
        last_ai_message = self.last_ai_message
        print(f"准备朗读消息: {last_ai_message[:50]}..." if last_ai_message and len(last_ai_message) > 50 else f"准备朗读消息: {last_ai_message}")
        
        if last_ai_message:
            # 使用新线程进行语音合成，避免阻塞UI
            def speak_text():
                try:
                    print("开始朗读...")
                    # 尝试设置中文语音
                    voices = self.engine.getProperty('voices')
                    if not hasattr(self, 'voice_settings_initialized_speak_last_message'):
                        chinese_voice = None
                        for voice in voices:
                            if 'zh-CN' in voice.id or 'Chinese' in voice.name:
                                chinese_voice = voice.id
                                print(f"找到中文语音: {voice.name} ({voice.id})")
                                break
                        
                        if chinese_voice:
                            print(f"使用中文语音: {chinese_voice}")
                            self.engine.setProperty('voice', chinese_voice)
                        self.voice_settings_initialized_speak_last_message = True
                    
                    print("调用 engine.say()...")
                    self.engine.say(last_ai_message)
                    print("朗读请求已发送")
                except Exception as e:
                    print(f"朗读出错：{e}")
                    import traceback
                    traceback.print_exc()
            
            # threading 模块已在文件顶部导入，不需要在这里再导入
            threading.Thread(target=speak_text).start()
        else:
            print("没有找到AI的回复可供朗读")

    def display_message(self, sender, message, callback=None):
        # 等待锁释放
        while self.typing_lock:
            self.master.after(10)  # 10毫秒检查一次
            
        # 获取锁
        self.typing_lock = True

        self.chat_history.config(state=tk.NORMAL)
        if sender == "灵犀1.1":
            self.chat_history.insert(tk.END, "🤖 ", 'ai_message')  # 使用机器人emoji作为头像
            self.chat_history.insert(tk.END, f"{sender}: ", ('sender', 'ai_message'))

        else:
            self.chat_history.insert(tk.END, f"{sender}: ", ('sender', 'user_message'))

        # 如果翻译功能开启，则翻译消息
        if self.translate_to_chinese_enabled.get() and sender == "灵犀1.1": # 只翻译AI的回复
            # 使用线程来运行异步翻译，避免阻塞UI
            self.last_ai_message = message # 更新最后一条AI消息，即使翻译开启
            def run_translation():

                loop = asyncio.new_event_loop()
                asyncio.set_event_loop(loop)
                translated_message = loop.run_until_complete(translate_text_async(message, to_lang='zh-CN'))
                self.master.after(0, self._update_message_after_translation, sender, translated_message, callback)

            threading.Thread(target=run_translation).start()
            return # 提前返回，等待翻译完成后再显示消息

        
        # 检查消息是否包含链接
        link_pattern = r"(https?://[^\s]+)"
        parts = re.split(link_pattern, message)
        
        try:
            for part in parts:
                if re.match(link_pattern, part):
                    # 如果是链接，则插入为可点击的链接
                    for char in part:
                        self.chat_history.insert(tk.END, char, 'link')
                        self.chat_history.see(tk.END)
                        self.chat_history.update()
                        self.master.after(10)
                else:
                    # 否则，按打字机效果插入普通文本
                    for char in part:
                        if sender == "灵犀1.1":
                            self.chat_history.insert(tk.END, char, 'ai_message')
                        else:
                            self.chat_history.insert(tk.END, char, 'user_message')
                        self.chat_history.see(tk.END)
                        self.chat_history.update()
                        self.master.after(10)
                        self.chat_history.see(tk.END)
                        self.chat_history.update()
                        self.master.after(10)
            if sender == "灵犀1.1":
                self.chat_history.insert(tk.END, '\n', 'ai_message')
            else:
                self.chat_history.insert(tk.END, '\n', 'user_message')
            self.chat_history.see(tk.END)
        finally:
            # 释放锁
            self.typing_lock = False
            if callback:
                callback()
            if sender == "灵犀1.1":
                self.speak_button.pack(pady=5)
                # 只有在不需要翻译时才自动朗读和显示复制按钮
                if not self.translate_to_chinese_enabled.get():
                    # 自动朗读消息
                    print(f"准备自动朗读消息: {message[:50]}..." if message and len(message) > 50 else f"准备自动朗读消息: {message}")
                    def speak_text():
                        try:
                            print("开始自动朗读...")
                            # 尝试设置中文语音
                            voices = self.engine.getProperty('voices')
                            if not hasattr(self, 'voice_settings_initialized_display_message'):
                                chinese_voice = None
                                for voice in voices:
                                    if 'zh-CN' in voice.id or 'Chinese' in voice.name:
                                        chinese_voice = voice.id
                                        print(f"找到中文语音: {voice.name} ({voice.id})")
                                        break
                                
                                if chinese_voice:
                                    print(f"使用中文语音: {chinese_voice}")
                                    self.engine.setProperty('voice', chinese_voice)
                                self.voice_settings_initialized_display_message = True
                            
                            print("调用 engine.say() (自动朗读)...")
                            self.engine.say(message)
                            print("自动朗读请求已发送")
                        except Exception as e:
                            print(f"自动朗读出错：{e}")
                            import traceback
                            traceback.print_exc()
                    # threading 模块已在文件顶部导入，不需要在这里再导入
                    threading.Thread(target=speak_text).start()
                    self.copy_button.pack(pady=5)
                self.last_ai_message = message # 更新最后一条AI消息

        self.chat_history.config(state=tk.DISABLED)



    def _update_message_after_translation(self, sender, translated_message, callback):
        # 这个函数在主线程中运行，用于更新UI
        self.chat_history.config(state=tk.NORMAL)
        # 重新插入发送者，因为之前的display_message已经返回了
        if sender == "灵犀1.1":
            self.chat_history.insert(tk.END, "🤖 ", 'ai_message')  # 使用机器人emoji作为头像
            self.chat_history.insert(tk.END, f"{sender}: ", ('sender', 'ai_message'))
        
        link_pattern = r"(https?://[^\s]+)"
        parts = re.split(link_pattern, translated_message)

        if sender == "灵犀1.1":
            message_tag = 'ai_message'
        else:
            message_tag = 'user_message'

        try:
            for part in parts:
                if re.match(link_pattern, part):
                    for char in part:
                        self.chat_history.insert(tk.END, char, 'link')
                        self.chat_history.see(tk.END)
                        self.chat_history.update()
                        self.master.after(10)
                else:
                    for char in part:
                        self.chat_history.insert(tk.END, char, message_tag)
                        self.chat_history.see(tk.END)
                        self.chat_history.update()
                        self.master.after(10)
            self.chat_history.insert(tk.END, '\n', message_tag)
            self.chat_history.see(tk.END)
        finally:
            self.typing_lock = False
            if callback:
                callback()
            if sender == "灵犀1.1":
                self.speak_button.pack(pady=5)
                # 自动朗读翻译后的消息
                print(f"准备朗读翻译后的消息: {translated_message[:50]}..." if translated_message and len(translated_message) > 50 else f"准备朗读翻译后的消息: {translated_message}")
                def speak_text():
                    try:
                        print("开始朗读翻译后的消息...")
                        # 尝试设置中文语音
                        if not hasattr(self, 'voice_settings_initialized_translation_message'):
                            voices = self.engine.getProperty('voices') # Moved inside for efficiency
                            chinese_voice = None
                            for voice in voices:
                                if 'zh-CN' in voice.id or 'Chinese' in voice.name:
                                    chinese_voice = voice.id
                                    print(f"找到中文语音: {voice.name} ({voice.id})")
                                    break
                            
                            if chinese_voice:
                                print(f"使用中文语音: {chinese_voice}")
                                self.engine.setProperty('voice', chinese_voice)
                            self.voice_settings_initialized_translation_message = True
                        
                        print("调用 engine.say() (翻译后朗读)...")
                        self.engine.say(translated_message)
                        print("翻译后朗读请求已发送")
                    except Exception as e:
                        print(f"朗读翻译后的消息出错：{e}")
                        import traceback
                        traceback.print_exc()
                # threading 模块已在文件顶部导入，不需要在这里再导入
                threading.Thread(target=speak_text).start()
                self.copy_button.pack(pady=5)
                self.last_ai_message = translated_message # 更新最后一条AI消息
        self.chat_history.config(state=tk.DISABLED)

    def send_message_event(self, event=None):
        self.send_message()

    def send_message(self):
        user_text = self.user_input_entry.get()
        if not user_text:
            return

        if self.typing_in_progress:
            return

        # 隐藏复制按钮和朗读按钮
        self.copy_button.pack_forget()
        self.speak_button.pack_forget()

        self.display_message("你", user_text)
        self.user_input_entry.delete(0, tk.END)

        self.user_input_entry.config(state='disabled')
        self.send_button.config(state='disabled')
        self.typing_in_progress = True

        def enable_input():
            self.user_input_entry.config(state='normal')
            self.send_button.config(state='normal')
            self.typing_in_progress = False

        if user_text.lower() == '再见':
            self.display_message("灵犀1.1", "再见！期待下次与你聊天！", None) # 不再传递回调函数
            return

        bot_response = chat_response(user_text, self.online_search_enabled.get())
        self.display_message("灵犀1.1", bot_response, enable_input)

if __name__ == '__main__':
    root = tk.Tk()
    gui = ChatbotGUI(root)
    root.mainloop()